package nbcp.db.mq


import org.springframework.amqp.core.AmqpTemplate
import org.springframework.amqp.core.BindingBuilder
import org.springframework.amqp.core.DirectExchange
import org.springframework.amqp.core.Queue
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory
import org.springframework.amqp.rabbit.core.RabbitAdmin
import org.springframework.amqp.rabbit.core.RabbitTemplate
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.cache.annotation.EnableCaching
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Lazy
import nbcp.base.extend.AsString
import nbcp.base.extend.HasValue
import nbcp.base.utils.SpringUtil
import nbcp.db.mongo.entity.SysLog
import nbcp.db.mongo.mor
import nbcp.db.mongo.*
import java.time.LocalDateTime
import javax.swing.Spring
import nbcp.db.mongo.*
import nbcp.db.mq.mqr
import javax.annotation.PostConstruct

@Configuration
@Lazy
open class MqConfig {

    @Autowired
    lateinit var cachingConnectionFactory: CachingConnectionFactory

//    @Bean
//    fun getConection():CachingConnectionFactory{
//
//        cachingConnectionFactory.setAddresses(addresses)
//        cachingConnectionFactory.username = username;
//        cachingConnectionFactory.setPassword(password)
//        cachingConnectionFactory.virtualHost = virtualHost
//        cachingConnectionFactory.isPublisherConfirms = publisherConfirms
//        cachingConnectionFactory.isPublisherReturns = publisherReturns
//        return cachingConnectionFactory
//    }

    @Bean
    @Lazy
    open fun mqTemplate(): RabbitTemplate {
        var ret = RabbitTemplate(cachingConnectionFactory)

        if (cachingConnectionFactory.isPublisherConfirms) {
            //如果消息没有到exchange,则confirm回调,ack=false
            //如果消息到达exchange,则confirm回调,ack=true
            ret.setConfirmCallback { correlationData, ack, cause ->
                if( correlationData == null) return@setConfirmCallback ;
                if( correlationData.id == null) return@setConfirmCallback ;

                if (ack) {
                    if (correlationData.id.HasValue) {
                        mor.system.mqLog.updateById(correlationData.id)
                                .set{it.arrivedAt to LocalDateTime.now()}
                                .exec();

                        if (mor.affectRowCount == 0) {
                            var ent = SysLog();
                            ent.type = "affectRowCount";
                            ent.module = "mq.confirm";
                            ent.msg = "affectRowCount=0"
                            ent.remark = "mq确认成功，但未更新,logId=${correlationData.id},${cause}"
                            mor.system.sysLog.insert(ent)
                        }
                    }
                } else {
                    mor.system.mqLog.updateById(correlationData.id)
                            .set(mor.system.mqLog.sendErrorMessage, "Mq确认失败: ${cause}")
                            .exec();

                    if (mor.affectRowCount == 0) {
                        var ent = SysLog();
                        ent.type = "affectRowCount";
                        ent.module = "mq.confirm";
                        ent.msg = "affectRowCount=0"
                        ent.remark = "mq确认失败，未更新,logId=${correlationData.id},${cause}"
                        mor.system.sysLog.insert(ent)
                    }
                }
            }
        }

        if (cachingConnectionFactory.isPublisherReturns) {
            ret.setMandatory(true);
            //exchange到queue成功,则不回调return
            //exchange到queue失败,则回调return(需设置mandatory=true,否则不回回调,消息就丢了)
            ret.setReturnCallback { message, replyCode, replyText, exchange, routingKey ->
                var logId = message.messageProperties.headers["log-id"].AsString()
                if (logId.HasValue) {
                    mor.system.mqLog.updateById(logId)
                            .set(mor.system.mqLog.sendErrorMessage, "${replyCode}-${replyText}-${exchange}:${routingKey}")
                            .exec();

                    if (mor.affectRowCount == 0) {
                        var ent = SysLog();
                        ent.type = "affectRowCount";
                        ent.module = "mq.confirm";
                        ent.msg = "affectRowCount=0"
                        ent.remark = "mq返回失败，未更新,${exchange}-${routingKey},logId=${logId},${message.body},${replyText}"
                        mor.system.sysLog.insert(ent)
                    }
                }
            }
        }
        return ret;
    }
}
